home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ddj1190.arc / TOOKE.ASC < prev    next >
Text File  |  1990-10-27  |  10KB  |  376 lines

  1. _OBJECT-ORIENTED DEBUGGING_
  2. by Simon Tooke
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. #ifndef STRING_H
  8. #define STRING_H
  9.  
  10. #include <string.h>
  11. #include <memory.h>
  12. #include <malloc.h>
  13.  
  14. #ifdef NULL
  15. # undef NULL
  16. #endif
  17. #define NULL 0
  18.  
  19. typedef enum { False, True } Boolean;
  20.  
  21. // a String is a simple implementation of a C++ string class
  22. class String 
  23. {
  24.     char     *s;        // actual pointer to text
  25.   public:
  26.     String(void)           { s = strdup(""); }
  27.     String(char *c)        { s = strdup(c); }
  28.     String(char *c, int n) { s = new char[n+1]; memcpy(s,c,n); s[n]=0; }
  29.     String(String &ss, char *c) { s = malloc(strlen(ss.s)+strlen(c)+1); 
  30.                                                  strcpy(s,ss.s); strcat(s,c); }
  31.     String(String &ss)     { s = strdup(ss.s); }
  32.     ~String(void)          { delete s; }
  33.     operator char *(void)  { return s; }
  34.     String& operator +(char *c)  { String *a = new String(*this,c); return *a;}
  35.     String& operator +=(char *c) { *this = *this + c; return *this; }
  36.     String& operator =(char *c)  { delete s; s = strdup(c); return *this; }
  37.     String& operator =(String& a){ delete s; s = strdup(a.s); return *this; }
  38.     operator ==(char *c) const;
  39.     operator ==(String *c) const;
  40. #ifdef DEBUG
  41.     void dump() const;
  42.     Boolean verify() const;
  43. #endif /*DEBUG*/
  44. };
  45.  
  46. // a StringListElement is a single item in a StringList
  47. class StringListElement 
  48. {
  49.     String s;                   // this String in the list
  50.     StringListElement *next;    // pointer to next element in list
  51.   public:
  52.     StringListElement(void)     : next(NULL), s("")  {}
  53.     StringListElement(char *c)  : next(NULL), s(c)   {}
  54.     StringListElement(char *c, int n) : next(NULL), s(c,n) {}
  55.     StringListElement(String &ss)     : next(NULL), s(ss)  {}
  56.     ~StringListElement(void)    { if (next) delete next; next=NULL; }
  57.     friend class StringList;
  58.     friend class StringListIterator;
  59. #ifdef DEBUG
  60.     void dump() const;
  61.     Boolean verify() const;
  62. #endif /*DEBUG*/
  63. };
  64.  
  65. // a StringList is a simple single-linked list of strings
  66. class StringList 
  67. {
  68.     StringListElement *head;    // first String in list
  69.     StringListElement *tail;    // last String in list
  70.   public:
  71.     StringList(void) : head(NULL), tail(NULL) {}
  72.     StringList(String& ss) { head = tail = new StringListElement(ss); }
  73.     StringList(char *ss)   { head = tail = new StringListElement(ss); }
  74.     ~StringList(void)      { if (head) { delete head; head=NULL; } }
  75.     String& find(char *s) const;
  76.     void clear(void)       { delete head; head = tail = NULL; }
  77.     StringList& operator +=(StringList& xx);
  78.     StringList& operator +=(char *ss);
  79.     StringList& operator +=(String& ss);
  80.     StringList& operator =(StringList& xx);
  81.     operator int();
  82.     friend class StringListIterator;
  83. #ifdef DEBUG
  84.     void dump() const;
  85.     Boolean verify() const;
  86. #endif /*DEBUG*/
  87. };
  88.  
  89. // a StringListIterator is a method of traversing a list of strings
  90. class StringListIterator 
  91. {
  92.     const StringList *list;    // StringList to be traversed
  93.     StringListElement *nxt;    // current String in StringList
  94.   public:
  95.     StringListIterator(void) : list(NULL), nxt(NULL) {}
  96.     StringListIterator(const StringList *l) : list(l), nxt(l->head) {}
  97.     String *next(void);
  98.     void reset()        { nxt = (list != NULL) ? list->head: NULL; }
  99.     int anymore() const { return (nxt != NULL); }
  100.     StringListIterator& operator =(const StringList& ss);
  101. #ifdef DEBUG
  102.     void dump() const;
  103.     Boolean verify() const;
  104. #endif /*DEBUG*/
  105. };
  106. #endif // STRING_H
  107.  
  108.  
  109. [LISTING TWO]
  110.  
  111. #include <stream.h>
  112. #include "String.h"
  113.  
  114. int main (int, char *[]) 
  115. {
  116.     String a("Hello ");
  117.     String *b = new String("world.");
  118.     String c;
  119.  
  120.     c = a + *b + "\n";
  121.  
  122.     cout << "a + b = " << (char *)c;
  123.     cout << "a = " << (char *)a << "\n";
  124.     cout << "b = " << (char *)*b << "\n";
  125.  
  126.     StringList l(a);
  127.     l += *b;
  128.  
  129.     l.dump();
  130. }
  131.  
  132.  
  133. [LISTING THREE]
  134.  
  135. #ifndef ASSERT_HDR
  136. #define ASSERT_HDR
  137.  
  138. #ifdef DEBUG
  139. extern void _assertRtn(char *, int);
  140.  
  141. # define assert(condition) \
  142.     if (condition) ; else _assertRtn(__FILE__,__LINE__);
  143.  
  144. #else /*ifndef DEBUG*/
  145.  
  146. # define assert(condition)
  147.  
  148. #endif
  149.  
  150. #endif /*ASSERT_HDR*/
  151.  
  152.  
  153. [LISTING FOUR]
  154.  
  155. #include <stream.h>
  156.  
  157. #ifdef DEBUG
  158. void _assertRtn(char *file, int line) 
  159. {
  160.     cerr << "\nAssertion Failure in file '" << file 
  161.                           << "' line " << line << "\n";
  162.     line = 0; line /= line;    // force core dump
  163. }    
  164. #endif
  165.  
  166.  
  167. [LISTING FIVE]
  168.  
  169. #include "String.h"
  170. #include "Assert.h"
  171.  
  172. #ifdef DEBUG
  173. # include <stream.h>
  174. #endif
  175.  
  176. /*****  String class  ******/
  177. // String comparison operator
  178. String::operator ==(char *c) const 
  179. {
  180.     assert(this->verify());
  181.  
  182.     // compare String to char array
  183.     return strcmp(s,c) == 0;
  184. }
  185.  
  186. // String comparison operator
  187. String::operator ==(String *c) const 
  188. {
  189.     assert(this->verify());
  190.     // compare String to String
  191.     return strcmp(s,(char *)c) == 0;
  192. }
  193. #ifdef DEBUG
  194. void String::dump(void) const 
  195. {
  196.     assert(this->verify());
  197.     cerr << "String(\"" << s << "\")";
  198. }
  199. Boolean String::verify(void) const 
  200. {
  201.     // Strings must always point to something.
  202.     if (s == NULL) return False;    
  203.     return True;
  204. }
  205. #endif
  206.  
  207. /****** StringList class (and StringListElement)  ******/
  208. StringList& StringList::operator +=(String& ss) 
  209. {
  210.     assert(this->verify());
  211.     if (tail) 
  212.     {
  213.         tail->next = new StringListElement(ss);
  214.         tail = tail->next;
  215.     }
  216.     else
  217.         head = tail = new StringListElement(ss);
  218.     return *this;
  219. }
  220. StringList& StringList::operator +=(char *ss) 
  221. {
  222.     assert(this->verify());
  223.     if (tail) 
  224.     {
  225.         tail->next = new StringListElement(ss);
  226.         tail = tail->next;
  227.     }
  228.     else
  229.         head = tail = new StringListElement(ss);
  230.     return *this;
  231. }
  232. StringList& StringList::operator +=(StringList& xx) 
  233. {
  234.     assert(this->verify());
  235.     // add new list to old list item by item
  236.     for (StringListElement *le=xx.head; le; le=le->next)
  237.         *this += le->s;
  238.     return *this;
  239. }
  240. // StringList assignment operator (performs deep copy)
  241. StringList& StringList::operator =(StringList& xx) 
  242. {
  243.     assert(this->verify());
  244.     // get rid of old list
  245.     clear();
  246.     // add new list to (clear) old list item by item
  247.     for (StringListElement *le=xx.head; le; le=le->next)
  248.         *this += le->s;
  249.     // return new copy of old list
  250.     return *this;
  251. }
  252. // (int)(StringList) cast returns number of strings in list
  253. StringList::operator int() 
  254. {
  255.     int count = 0;
  256.     StringListIterator ll(this);
  257.  
  258.     assert(this->verify());
  259.     while (ll.next() != NULL)
  260.         count++;
  261.     return count;
  262. }
  263. #ifdef DEBUG
  264. //
  265. //        dump() - display instance in format "StringList(...)"
  266. //
  267. void StringList::dump(void) const 
  268. {
  269.     // check consistancy
  270.     assert(this->verify());
  271.     // print header
  272.     cerr << "StringList(";
  273.     // use StringListElement::dump() to recursively display all members
  274.     if (head != NULL) head->dump();
  275.     // print trailer
  276.     cerr << ")\n";
  277. }
  278. Boolean StringList::verify(void) const 
  279. {
  280.     // if there are elements in this list, ensure they are valid.
  281.     // (note that head->verify() ensures the entire list is valid.)
  282.     if ((head!=NULL) && !head->verify()) return False;
  283.  
  284.     // Both the head and tail must either be null or non-null.
  285.     if ((head!=NULL) && (tail==NULL)) return False;
  286.     if ((head==NULL) && (tail!=NULL)) return False;
  287.  
  288.     return True;
  289. }
  290. #endif /*DEBUG*/
  291.  
  292. #ifdef DEBUG
  293. void StringListElement::dump(void) const 
  294. {
  295.     assert(this->verify());
  296.     s.dump();
  297.     if (next != NULL) 
  298.     {
  299.         cerr << ',';
  300.         next->dump();
  301.     }
  302. }
  303. Boolean StringListElement::verify(void) const 
  304. {
  305.     // An element of a list of Strings must point to a valid String.
  306.     if ((char *)(s) == NULL) return False;
  307.     if (!s.verify()) return False;
  308.     // If there is another element within this list, it must be valid.
  309.     if ((next!=NULL) && !next->verify()) return False;
  310.  
  311.     return True;
  312. }
  313. #endif
  314.  
  315. /****** StringListIterator class  ******/
  316. // assignment operator
  317. StringListIterator& StringListIterator::operator =(const StringList& ss) 
  318. {
  319.     assert(this->verify());
  320.     list = &ss;
  321.     nxt = ss.head;
  322.     return *this;
  323. }
  324. // get next item in list of strings pointed to by iterator
  325. String *StringListIterator::next(void) 
  326. {
  327.     assert(this->verify());
  328.     if (list == NULL) return NULL;   // no StringList, so no next item
  329.     if (nxt == NULL) return NULL;    // at end of list, so no next item
  330.     String *aa = &(nxt->s);          // save pointer to String
  331.     nxt = nxt->next;                 // point to next item in list
  332.     return aa;                       // return pointer to String
  333. }
  334. #ifdef DEBUG
  335. Boolean StringListIterator::verify(void) const 
  336. {
  337.     // if there is a list available, verify it.
  338.     if (!list->verify()) return False;
  339.  
  340.     // if we haven't reached the end of the list, 
  341.     // verify the next element
  342.     if (nxt != NULL && !nxt->verify()) return False;
  343.  
  344.     // everything appears correct
  345.     return True;
  346. }
  347. #endif /*DEBUG*/
  348.  
  349.  
  350. [LISTING SIX]
  351.  
  352. CC = CC
  353. CFLAGS = -DDEBUG
  354.  
  355. prog : main.o String.o lib.o
  356.     $(CC) main.o String.o lib.o -o prog
  357.  
  358. String.o : String.C String.h
  359.     $(CC) -c $(CFLAGS) String.C
  360.  
  361. main.o : main.C String.h
  362.     $(CC) -c $(CFLAGS) main.C
  363.  
  364. lib.o : lib.C
  365.     $(CC) -c $(CFLAGS) lib.C
  366.  
  367. clean :
  368.     rm -f *.o a.out core
  369.  
  370. clobber : clean
  371.     rm -f prog
  372.  
  373.  
  374.  
  375.  
  376.